#!/bin/env python3

import os
import sys
from subprocess import call
from os import remove, close
from tempfile import mkstemp
from tempfile import  NamedTemporaryFile
from shutil import move


def deriveAppBitsFiles(allBitsFiles):
    import re
    print("======>>"+"find APP bits files")
    new_file = open("AppBitsFiles",'w')
    old_file = open(allBitsFiles)

    #/^(?:(?!PATTERN).)*$/;    # Matches strings not containing PATTERN^(?=.*?\bdog\b)((?!cat).)*$
    appPattern = re.compile(r'^(?:(?!REF).)*$')
    for line in old_file:
        if  appPattern.search(line) :
            new_file.write(line)
        else:
            continue
    #close temp file
    new_file.close()
    old_file.close()

def findTargetAppBitsFile(appBitsFiles,targetAppBitsFile):
    import re
    old_file = open(appBitsFiles)
    appPattern = re.compile(targetAppBitsFile)
    for line in old_file:
        if appPattern.search(line):
            old_file.close()
            return True
        else:
            continue
    #close temp file
    old_file.close()
    return False

def findAntCmpFile(ant):
    import re

    antCmpFiles = open("AntCmpFiles")
    antPattern = re.compile(ant)

    retcode = 1
    targetAntCmp = ''
    for line in antCmpFiles:
        if antPattern.search(line):
            retcode = 0
            targetAntCmp = line
        else:
            continue
    #close temp file
    antCmpFiles.close()

    if retcode == 0:
        return targetAntCmp
    else :
        return None



def findIqCompareFailureAnts():
    import re

    findM01logFile= """find \
      . \
      -regex '.*_M01\.log$'\
      -type f -printf '%f\\n' > M01log """

    print("======>>"+"find M01.log ")
    try:
        retcode = call(findM01logFile, shell=True)
        if retcode < 0:
            print("Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print("Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print("Execution failed:", e, file=sys.stderr)

    m01LogFiles= open("M01log")
    antPattern = re.compile(r'ERROR:\s*Compare\s*of\s*(ANT[0-9]*)\s*failed')
    #antPattern = re.compile(r'ERROR')
    ants=[];

    with open("M01log",'r') as f:
        firstline= f.readline()
        firstline.encode()
        M01log = open(firstline.rstrip('\n'),'r')
        for line in M01log:
            m=antPattern.search(line)
            if m is not None:
                ants.append(m.group(1))
            else:
                continue
    #close temp file
    M01log.close()
    m01LogFiles.close()

    return ants


def deriveRefBitsFiles(allBitsFiles):
    import re
    print("======>>"+"find REF bits files")
    new_file = open("RefBitsFiles",'w')
    old_file = open(allBitsFiles)
    appPattern = re.compile(r'SPECMAN.*(?=REF).*\.bits')
    for line in old_file:
        if appPattern.search(line):
            new_file.write(line)
        else:
            continue
    #close temp file
    new_file.close()
    old_file.close()

def cmpbits(path):
    import re
    print("start cmpbits")
    if path == '':
        path = '.'
    parentDir = os.getcwd()
    os.chdir(path)
    bitsCwd = os.getcwd()
    #findcmdSmall = """find \
    #  . \
    #  -regex '.*\.\(\
    #bits\
    #\|pl\|pm\|perl\
    #\|py\|par\
    #\|sig\
    #\)'\
    #  -type f -printf '%f\\t%p\\t1\\n' > filetags """
    findBitsFiles = """find \
      . \
      -regex '.*\.bits$'\
      -type f -printf '%f\\n' > BitsFiles """

    if os.path.exists("BitsFiles"):
        os.remove("BitsFiles")
    print("======>>"+"find all bits files")
    try:
        retcode = call(findBitsFiles, shell=True)
        if retcode < 0:
            print("Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print("Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print("Execution failed:", e, file=sys.stderr)

    findAntCmpFiles= """find \
      . \
      -regex '.*_M01_ANT[0-9]*\.cmp$'\
      -type f -printf '%f\\n' > AntCmpFiles """

    if os.path.exists("AntCmpFiles"):
        os.remove("AntCmpFiles")
    print("======>>"+"find AntCmp files ")
    try:
        retcode = call(findAntCmpFiles, shell=True)
        if retcode < 0:
            print("Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print("Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print("Execution failed:", e, file=sys.stderr)


    if os.path.exists("AppBitsFiles"):
        os.remove("AppBitsFiles")
    deriveAppBitsFiles("BitsFiles")
    if os.path.exists("RefBitsFiles"):
        os.remove("RefBitsFiles")
    deriveRefBitsFiles("BitsFiles")

    if os.path.exists("AppRefBitsCompResult"):
        os.remove("AppRefBitsCompResult")

    print("======>>"+"new AppRefBitsCompResult")
    try:
        retcode = call("touch  AppRefBitsCompResult", shell=True)
        if retcode < 0:
            print("Child was terminated by signal", -retcode, file=sys.stderr)
        else:
            print("Child returned", retcode, file=sys.stderr)
    except OSError as e:
        print("Execution failed:", e, file=sys.stderr)



    #appBitsFiles = open("AppBitsFiles",'r')
    refBitsFiles = open("RefBitsFiles",'r')

    fh, tmp_one_cmp_result_path = mkstemp()
    tmp_one_file = open(tmp_one_cmp_result_path,'w+b')
    appRefBitsCompResult_file= open("AppRefBitsCompResult",'w+b')
    allBitsMisMatch = False


    #for appBitsFile, refBitsFile in zip(appBitsFiles,refBitsFiles):
    #since the bits file order might not exactly same in two files, so can not simply follow up the iterator order
    refPattern=re.compile(r'_REF')
    for refBitsFile in refBitsFiles:
        refMapAppBitsFile = str(refPattern.sub('',refBitsFile))
        #print('refMapApp:'+ refMapAppBitsFile)
        if findTargetAppBitsFile("AppBitsFiles",refMapAppBitsFile):
            #print("find mapped appBitsFile:"+refMapAppBitsFile)
            try:
                files = ' '.join((refMapAppBitsFile.rstrip('\n'),refBitsFile.rstrip('\n')))
                #retcode = call("/usr/bin/gvimdiff "+ files, shell=True)
                #retcode = call("/usr/atria/bin/cleartool diff -g "+ files, shell=True, cwd=bitsCwd)
                retcode = call("/usr/atria/bin/cleartool diff  "+ files + ">" + tmp_one_cmp_result_path, shell=True, cwd=bitsCwd)
                ##retcode=0
                allBitsMisMatch = allBitsMisMatch or retcode
                if retcode < 0:
                    print("Child was terminated by signal", -retcode, file=sys.stderr)
                elif retcode ==0 :
                    files_rec = '\n'.join((refMapAppBitsFile.rstrip('\n'),refBitsFile))
                    appRefBitsCompResult_file.write(files_rec.encode())
                    appRefBitsCompResult_file.write('\n'.encode())
                    print("Child returned", retcode, file=sys.stderr)
                else:
                    files_rec = '\n'.join((refMapAppBitsFile.rstrip('\n'),refBitsFile))
                    appRefBitsCompResult_file.write(files_rec.encode())
                    for line in tmp_one_file:
                        appRefBitsCompResult_file.write(line)
                    appRefBitsCompResult_file.write('\n'.encode())
                    print("Child returned", retcode, file=sys.stderr)
            except OSError as e:
                print("Execution failed:", e, file=sys.stderr)
        else:
            print('no expected '+ refMapAppBitsFile + ' can be found')

    move(tmp_one_cmp_result_path,"AppRefBitsCompResult")
    #close temp file
    tmp_one_file.close()
    close(fh)
    os.chdir(parentDir)
    return allBitsMisMatch

def postResultView(allBitsMisMatch, path):
    parentDir = os.getcwd()
    os.chdir(path)
    bitsCwd = os.getcwd()

    if allBitsMisMatch is False: #check cmpfiles
        print("======>>"+"all Bits files match each other, check chip level diff info")
        try:
            ants = findIqCompareFailureAnts()
            targetCmpfiles=''
            for ant in ants:
                antCmp = findAntCmpFile(ant)
                if antCmp is not None:
                    targetCmpfiles = targetCmpfiles+' '+antCmp.rstrip('\n')

            retcode = call("gvim -p"+targetCmpfiles,shell=True,cwd=bitsCwd)
            if retcode < 0:
                print("Child was terminated by signal", -retcode, file=sys.stderr)
            else:
                print("Child returned", retcode, file=sys.stderr)
        except OSError as e:
            print("Execution failed:", e, file=sys.stderr)
    else:
         print("======>>"+"some Bits file mis-match, check AppRefBitsCompResult for detail")
         try:
             retcode = call("gvim AppRefBitsCompResult", shell=True,cwd=bitsCwd)
             if retcode < 0:
                 print("Child was terminated by signal", -retcode, file=sys.stderr)
             else:
                 print("Child returned", retcode, file=sys.stderr)
         except OSError as e:
             print("Execution failed:", e, file=sys.stderr)
    os.chdir(parentDir)


def main():
    from argparse import ArgumentParser
    from argparse import ArgumentDefaultsHelpFormatter
    parser = ArgumentParser(\
            description = 'compare the bits files between APP and REF. in target \
            PECMAN\\SPECMAN_*\\output \
            note: generate those bits files with DCL_ChipRate_Decoder first ',\
            formatter_class = ArgumentDefaultsHelpFormatter\
            )
    parser.add_argument('-p', default = ['.'], nargs = '+',dest = 'paths', help= 'paths contains App & Ref bits files')

    args = parser.parse_args()
    for path in args.paths :
        print(path)
        #cmpbits(path)
        postResultView(cmpbits(path),path)





if __name__ == "__main__":
  main()
